package com.blb.java10security.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import javax.sql.DataSource;

/**
 * Security配置类
 */
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    /**
     * 提供密码加密编码器给IOC容器
     * @return
     */
    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Autowired
    private UserDetailsService userDetailsService;

    /**
     * 验证配置
     * Authentication 验证，Authorization 授权
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //配置数据库登录验证
        auth.userDetailsService(userDetailsService);
//        //内存中的登录验证
//        auth.inMemoryAuthentication()
//                .withUser("admin") //设置账号
//                .password(bCryptPasswordEncoder.encode("123456"))
//                 //.roles("ADMIN","USER") //设置角色
//                .authorities("ROLE_ADMIN","ROLE_USER","LIST_USER","ADD_USER")  //设置权限 roles方法会失效 带ROLE_ 加角色
//                .and()
//                .withUser("zhangsan")
//                .password(bCryptPasswordEncoder.encode("123456"))
//                .roles("USER");
    }

    /**
     * 配置登录处理
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //请求授权
        http.authorizeRequests()
                .antMatchers("/login.html","/login").permitAll() //配置直接放行的请求
                .antMatchers("/admin.html").hasRole("管理员") //此页面必须有ADMIN角色才能访问
                .antMatchers("/user.html").hasRole("仓管") //此页面必须有USER角色才能访问
                .antMatchers("/user-list.html").hasAuthority("销售管理") //有LIST_USER权限才能访问
                .antMatchers("/user-add.html").hasAuthority("客户信息") //有ADD_USER权限才能访问
                .anyRequest().authenticated() //其它请求需要登录验证
                .and()
                .formLogin() //登录相关配置
                .loginProcessingUrl("/login") //登录处理的url
                .loginPage("/login.html") //配置登录页面url
                .defaultSuccessUrl("/hello.html") //登录成功后跳转的页面
                .and()
                .logout() //注销配置
                .logoutUrl("/logout")
                .logoutSuccessUrl("/login.html")
                .and()
                .rememberMe()
                .rememberMeParameter("rememberMe") //表单的名称
                .tokenRepository(persistentTokenRepository) //设置持久化对象
                .tokenValiditySeconds(10); //记住我的时间
    }

    @Autowired
    private DataSource dataSource;

    @Autowired
    private PersistentTokenRepository persistentTokenRepository;

    /**
     * RememberMe配置的持久化对象
     * @return
     */
    @Bean
    public PersistentTokenRepository persistentTokenRepository(){
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        jdbcTokenRepository.setDataSource(dataSource);
        //设置启动后键rememberMe表
//        jdbcTokenRepository.setCreateTableOnStartup(true);
        return jdbcTokenRepository;
    }
}
